﻿//-----------------------------------------------------------------------------
//<filedescription file="TaskSequenceActionUtils.cs" company="Microsoft">
//  <copyright>
//     Copyright © Microsoft Corporation.  All rights reserved.
//     ***  DESIGNATED SAMPLE CODE (per the included software license terms) ***
//      THIS CODE SAMPLE IS MADE AVAILABLE TO YOU WITHOUT WARRANTY OF ANY KIND
//      AND CONFERS NO RIGHTS ON YOU WHATSOEVER EXCEPT THE RIGHT TO REVIEW IT
//      SOLELY AS A REFERENCE.  THE ENTIRE RISK OF USE OR RESULTS FROM USE OF
//      THIS CODE SAMPLE REMAINS WITH YOU.
//  </copyright>
//  <purpose>
//     More general utility methods for use within the OEM Deployment Kit.
//     More specific to OSD than the Integration Kit Utils.
//  </purpose>
//  <notes>
//  </notes>
//</filedescription>
//-----------------------------------------------------------------------------


#region Using directives

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Threading;
using System.Security;
using System.Text.RegularExpressions;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Windows.Forms;
using Microsoft.Win32;
using Microsoft.ConfigurationManagement.AdminConsole;
using Microsoft.ConfigurationManagement.ManagementProvider;
using Microsoft.ConfigurationManagement.AdminConsole.TaskSequenceEditor;
using Microsoft.ConfigurationManagement.AdminConsole.Common;
using Microsoft.ConfigurationManagement.AdminConsole.OsdCommon;
using Microsoft.ConfigurationManagement.IntegrationDevelopmentKit;
#endregion

namespace Microsoft.ConfigurationManagement.OemDeployment
{
    /// <summary>
    /// ServerDeploymentCustomAction
    /// </summary>
    public partial class ServerDeploymentCustomAction : SmsOsdEditorPageControl
    {
        #region Constants

        /// <summary>
        /// 
        /// </summary>
        public const string TASK_SEQUENCE_HELP_ID = "27b1bcd0-a0ac-4bbe-ae86-01c4bd052a4d";

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param taskName="myPropertyManager"></param>
        /// <param taskName="configurationXml"></param>
        /// <param taskName="query"></param>
        /// <returns></returns>
        private bool BuildClientTaskSequenceCommands(IResultObject propertyManager, XmlDocument configurationXml, string query)
        {
            //Logline("BuildClientTaskSequenceCommands():    starting...");

            XmlDocument taskFile = CreateTaskStepXml();

            if (taskFile != null)
            {
                //Logline("BuildClientTaskSequenceCommands():  taskFile passed in OK");
                XmlNode nodeCfg = IntegrationKitUtilities.GetXmlNode(configurationXml, query);
                if (nodeCfg != null)
                {
                    //Logline("BuildClientTaskSequenceCommands():   found the node. Now getting client tasks");
                    taskFile = ImportClientTasks(propertyManager, taskFile, nodeCfg, "PreConfigurationTasks");
                    taskFile = ImportClientTasks(propertyManager, taskFile, nodeCfg, "ConfigurationTask");
                    taskFile = ImportClientTasks(propertyManager, taskFile, nodeCfg, "PostConfigurationTasks");
                    taskFile = AddUserVariables(propertyManager, taskFile, "ConfigurationTask");

                    if (IntegrationKitUtilities.SaveXmlToPropertyManager(propertyManager, "ClientActions", taskFile))
                    {
                        //Logline("BuildClientTaskSequenceCommands():  Saved to Property Manager");
                        return true;
                    }
                    else
                    {
                        //Logline("BuildClientTaskSequenceCommands():  Error: unable to save to Property Manager!");
                        return false;
                    }
                }
                else
                {
                    //Logline("BuildClientTaskSequenceCommands():  Error: Configuration type not found!");
                    return false;
                }
            }
            else
            {
                //did not build task file
                //Logline("BuildClientTaskSequenceCommands():  Task XML could not be built. Error!");
                return false;
            }
            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param taskName="myPropertyManager"></param>
        /// <param taskName="taskFile"></param>
        /// <param taskName="configurationTypeNode"></param>
        /// <param taskName="taskSetName"></param>
        /// <returns></returns>
        private XmlDocument ImportClientTasks(IResultObject propertyManager, XmlDocument taskFile, XmlNode configurationTypeNode, string taskSetName)
        {
                //Logline("ImportClientTasks:  starting...");
                if (taskFile == null)
                {
                    //Logline("ImportClientTasks(): XML document passed in was null.");
                    //Logline("ImportClientTasks():    ending...");
                    return taskFile;
                }
                if (configurationTypeNode == null)
                {
                    //Logline("ImportClientTasks():  XML node passed in was null.");
                    //Logline("ImportClientTasks():    ending...");
                    return taskFile;
                }
                if (string.IsNullOrEmpty(taskSetName))
                {
                    //Logline("ImportClientTasks():  taskSetName propertyValue passed in was null");
                    //Logline("ImportClientTasks():    ending...");
                    return taskFile;
                }
                //found the configuration type. Now find associated tasks and drop them in
                XmlNode taskNode = null;
                XmlNode replacedNode = null;
                //Logline("ImportClientTasks:  getting top level node for the task set : " + taskSetName);

                taskNode = IntegrationKitUtilities.GetXmlNode(configurationTypeNode, "./" + taskSetName);
                if (taskNode != null)
                {
                    //Logline("ImportClientTasks():  Found a task node from this query.");

                    replacedNode = null;
                    replacedNode = ReplaceVarsInTaskStepXml(propertyManager, taskNode);
                    if (replacedNode != null)
                    {
                        XmlNode imported = taskFile.ImportNode(replacedNode, true);
                        taskFile.DocumentElement.AppendChild(imported);
                        //Logline("ImportClientTasks():    ending...");
                        return taskFile;
                    }
                    else
                    {
                        //Logline("ImportClientTasks():  There was an error replacing the variables in the node!");
                        return taskFile;
                    }
                }
                else
                {
                    //Logline("ImportClientTasks():  No task steps under the " + taskSetName + " configuration type.");
                    //Logline("ImportClientTasks():    ending...");
                    return taskFile;
                }
                        
                   
               
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param taskName="propertyManager"></param>
        /// <param taskName="taskFile"></param>
        /// <param taskName="taskSetName"></param>
        /// <returns></returns>
        private XmlDocument AddUserVariables(IResultObject propertyManager, XmlDocument taskFile, string taskSetName)
        {
             //Logline("AddUserVariables:  starting...");
                if (taskFile != null)
                {
                    if (!string.IsNullOrEmpty(taskSetName))
                    {
                        //found the configuration type. Now find associated tasks and drop them in
                        XmlNode taskNode = null;
                        //Logline("AddUserVariables:  getting top level node for the task set : " + taskSetName + "/Task");

                        taskNode = IntegrationKitUtilities.GetXmlNode(taskFile, "//" + taskSetName + "/Task");
                        if (taskNode != null)
                        {
                            //Logline("AddUserVariables():  Found a task node from this query.");

                            //===[ begin modification ]====================
                            // Modified 9/8/08 by rhearn
                            // - Changed local variable definition to use existing property and prevent naming conflict

                            //XmlDocument propertiesXml = IntegrationKitUtilities.GetXmlFromPropertyManager(propertyManager, "ControlValues");
                            if (propertiesXml == null)
                            {
                                propertiesXml = IntegrationKitUtilities.GetXmlFromPropertyManager(propertyManager, "ControlValues");
                            }
                            
                            //===[ end modification ]====================
                            
                            
                            
                            XmlNodeList varNodes = IntegrationKitUtilities.GetXmlNodeList(propertiesXml, "//Value[@taskName='AddlVariable']");

                            if (varNodes != null)
                            {
                                foreach (XmlNode varNode in varNodes)
                                {
                                    string content = varNode.InnerXml.ToString();
                                    if (content != null)
                                    {
                                        content = content.Replace("<![CDATA[", "");
                                        content = content.Replace("]]>", "");
                                        string[] newContent = content.Split(new char[] { '|' });

                                        //<SetEnvironmentVariable SetAsType ="SysAndTsVariable" VarName="taskName" VarType="String" VarValue="propertyValue"/>

                                        XmlElement elem = taskFile.CreateElement("SetEnvironmentVariable");
                                        //Logline("AddUserVariables():  Created a new SetEnvironmentVariable node");

                                        XmlAttribute attribSetAsType = taskFile.CreateAttribute("SetAsType");
                                        attribSetAsType.Value = "SysAndTsVariable";
                                        elem.SetAttributeNode(attribSetAsType);
                                        //Logline("AddUserVariables():  Created a new SetEnvironmentVariable attribute 'SetAsType': " + "SysAndTsVariable");

                                        XmlAttribute attribVarName = taskFile.CreateAttribute("VarName");
                                        attribVarName.Value = newContent[0];
                                        elem.SetAttributeNode(attribVarName);
                                        //Logline("AddUserVariables():  Created a new SetEnvironmentVariable attribute 'VarName': " + newContent[0]);

                                        XmlAttribute attribVarType = taskFile.CreateAttribute("VarType");
                                        attribVarType.Value = "String";
                                        elem.SetAttributeNode(attribVarType);
                                        //Logline("AddUserVariables():  Created a new SetEnvironmentVariable attribute 'VarType': " + "String");

                                        XmlAttribute attribVarValue = taskFile.CreateAttribute("VarValue");
                                        attribVarValue.Value = newContent[1];
                                        elem.SetAttributeNode(attribVarValue);
                                        //Logline("AddUserVariables():  Created a new SetEnvironmentVariable attribute 'VarValue': " + newContent[1]);

                                        taskNode.InsertAfter(elem, taskNode.LastChild);
                                        //Logline("AddUserVariables():  Added SetEnvironmentVariable node to the task");

                                    }
                                    else
                                    {
                                        //Logline("AddUserVariables:  Value node found, but no propertyValue string found in XML for addl variable (valid xml propertiesXml, valid node, but no propertyValue)");
                                    }
                                }
                                //Logline("AddUserVariables():   ending...");
                                return taskFile;
                            }
                            else
                            {
                                //Logline("AddUserVariables():  There was an error adding the variables to the task!");
                                return taskFile;
                            }
                        }
                        else
                        {
                            //Logline("AddUserVariables():  No task steps found under //" + taskSetName + "/Task .");
                            //Logline("AddUserVariables():    ending...");
                            return taskFile;
                        }
                    }
                    else
                    {
                        //Logline("AddUserVariables():  taskSetName propertyValue passed in was null");
                        //Logline("AddUserVariables():    ending...");
                        return taskFile;
                    }
                }
                else
                {
                    //Logline("AddUserVariables(): XML document passed in was null.");
                    //Logline("AddUserVariables():    ending...");
                    return taskFile;
                }
            
        }
               
        /// <summary>
        /// 
        /// </summary>
        /// <param taskName="myPropertyManager"></param>
        /// <param taskName="topNode"></param>
        /// <returns></returns>
        private XmlNode ReplaceVarsInTaskStepXml(IResultObject propertyManager, XmlNode topNode)
        {
            
            //Logline("ReplaceVarsInTaskStepXml():    starting...");
            //get all "Task" nodes under this node
            XmlNodeList taskNodes = IntegrationKitUtilities.GetXmlNodeList(topNode, "./Task");
            if (taskNodes == null)
            {
                //Logline("ReplaceVarsInTaskStepXml():  No task nodes found");
                //Logline("ReplaceVarsInTaskStepXml():    ending...");
                return null;
            }
            //Logline("ReplaceVarsInTaskStepXml():    Found task nodes.");
            foreach (XmlNode taskNode in taskNodes)
            {
                // now get all "Parameter" nodes in this task
                XmlNodeList paramNodes = IntegrationKitUtilities.GetXmlNodeList(taskNode, "./Parameter");
                if (paramNodes != null)
                {
                    foreach (XmlNode paramNode in paramNodes)
                    {
                        string paramType = IntegrationKitUtilities.GetXmlAttribute(paramNode, "ParamType");
                        if (string.Compare(paramType, "ControlValue", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            //Logline("ReplaceVarsInTaskStepXml():  Found a 'ControlValue' parameter. Replacing with propertyValues from the form.");
                            ReplaceCmdLineVarsInNode(propertyManager, paramNode, "ParamType", "ParamValue");
                        }
                        else if (string.Compare(paramType, "StdOut", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            //Logline("ReplaceVarsInTaskStepXml():  Found a 'StdOut' parameter. Replacing with propertyValues from the form.");
                            ReplaceCmdLineVarsInNode(propertyManager, paramNode, "ParamType", "ParamValue");
                        }
                        else if (string.Compare(paramType, "StdErr", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            //Logline("ReplaceVarsInTaskStepXml():  Found a 'StdErr' parameter. Replacing with propertyValues from the form.");
                            ReplaceCmdLineVarsInNode(propertyManager, paramNode, "ParamType", "ParamValue");
                        }
                    }
                }
                // now get all "ReturnFile" nodes in this task
                XmlNodeList fileNodes = IntegrationKitUtilities.GetXmlNodeList(taskNode, "./ReturnFile");
                if (fileNodes != null)
                {
                    foreach (XmlNode fileNode in fileNodes)
                    {
                        if (string.Compare(IntegrationKitUtilities.GetXmlAttribute(fileNode, "FileType"), "ControlValue", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            //Logline("ReplaceVarsInTaskStepXml():  Found a 'ControlValue' parameter. Replacing with propertyValues from the form.");
                            ReplaceCmdLineVarsInNode(propertyManager, fileNode, "FileType", "FileName");
                        }

                        string copyToDest = IntegrationKitUtilities.GetXmlAttribute(fileNode, "CopyTo");
                        if (copyToDest.Length > 0)
                        {
                            //Logline("ReplaceVarsInTaskStepXml():  Checked for a propertyValue in the 'CopyTo' attribute. Value exists.");
                        }
                        else
                        {
                            //Logline("ReplaceVarsInTaskStepXml():  No propertyValue in the 'CopyTo' attribute. Copying in the mapped drive propertyValue.");
                            string mappedDrive = GetPropertyFromValuesXml(IntegrationKitUtilities.GetXmlFromPropertyManager(propertyManager, "ControlValues"), "MappedDrive");
                            fileNode.Attributes["CopyTo"].Value = mappedDrive;
                        }
                    }
                }
            }
        
            //Logline("ReplaceVarsInTaskStepXml():    ending...");
            return topNode;
            

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param taskName="propertyManager"></param>
        /// <param taskName="node"></param>
        /// <param taskName="propertyName"></param>
        /// <param taskName="propertyValue"></param>
        /// <returns></returns>
        private XmlNode ReplaceCmdLineVarsInNode(IResultObject propertyManager, XmlNode node, string propertyName, string propertyValue)
        {
            //===[ begin modification ]====================
            // Modified 9/8/08 by rhearn
            // - Changed local variable definition to use existing property and prevent naming conflict
            if (propertiesXml == null)
            {
                propertiesXml = IntegrationKitUtilities.GetXmlFromPropertyManager(propertyManager, "ControlValues");
            }
            //XmlDocument propertiesXml = IntegrationKitUtilities.GetXmlFromPropertyManager(propertyManager, "ControlValues");
            //===[ end modification ]====================
            
            if (propertiesXml == null)
            {
                //Logline("ReplaceVarsInTaskStepXml():  ### ERROR ### properties XML file propertyValue was null!");
                return null;
            }
            if (node == null)
            {
                //Logline("ReplaceCmdLineVarsInNode:  node passed in was null");
                return null;
            }
            if (propertyName == null)
            {
                //Logline("ReplaceCmdLineVarsInNode():  ### ERROR ### the taskName of the type attribute passed in was null");
                return null;
            }
            if (propertyValue == null)
            {
                //Logline("ReplaceCmdLineVarsInNode():  ### ERROR ### the property propertyValue passed in was null");
                return null;
            }
            
            string paramType = node.Attributes[propertyName].Value;
            if (string.Compare(IntegrationKitUtilities.GetXmlAttribute(node, propertyValue), "cmdline", StringComparison.OrdinalIgnoreCase) == 0)
            {
                // this means we're supposed to replace the "ParamValue" attribute with the contents of the command line control

                //Check to see if this is an embedded file
                string embeddedFile = GetPropertyFromValuesXml(propertiesXml, "EmbeddedFile");
                if (string.IsNullOrEmpty(embeddedFile) == false)
                {
                    node.Attributes[propertyName].Value = "EmbeddedFile";
                    return node;
                }
                else
                {
                    string nodeValue = GetPropertyFromValuesXml(propertiesXml, "CommandLineWithPath");
                    if (nodeValue != null)
                    {
                        //Logline("ReplaceCmdLineVarsInNode(): Value of the 'CommandLine' control is: " + nodeValue);
                        node.Attributes[propertyValue].Value = nodeValue;

                        if ((string.Compare(paramType, "StdOut", StringComparison.OrdinalIgnoreCase) == 0) ||
                            (string.Compare(paramType, "StdErr", StringComparison.OrdinalIgnoreCase) == 0))
                        {
                            //Logline("ReplaceCmdLineVarsInNode(): Leaving parameter type as StdOut or StdErr");
                        }

                        else if (string.Compare(GetPropertyFromValuesXml(propertiesXml, "CmdLineIsFileName"), "true", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            //Logline("ReplaceCmdLineVarsInNode(): Changing parameter type to String");
                            node.Attributes[propertyName].Value = "Filename";
                        }
                        else
                        {
                            //Logline("ReplaceCmdLineVarsInNode(): Changing parameter type to String");
                            node.Attributes[propertyName].Value = "String";
                        }
                        //Logline("ReplaceCmdLineVarsInNode(): Successfully put the propertyValues in the taskNode: ");
                        return node;
                    }
                    else
                    {
                        //Logline("ReplaceCmdLineVarsInNode():  ### ERROR ### could not find a value in properties XML for the CommandLine control value");
                        return null;
                    }
                }
            }
            else if (string.Compare(IntegrationKitUtilities.GetXmlAttribute(node, propertyValue), "addlcmdline", StringComparison.OrdinalIgnoreCase) == 0)
            {
                string useAddlCmdLine = GetPropertyFromValuesXml(propertiesXml, "CkAddlCmdLine");
                if ((useAddlCmdLine != null) && (string.Compare(useAddlCmdLine, "true", StringComparison.OrdinalIgnoreCase) == 0))
                {
                    //string nodeValue = GetPropertyFromValuesXml(propertiesXml, "AddlCommandLineWithPath");
                    //if (nodeValue != null)
                    //{
                    //Logline("ReplaceCmdLineVarsInNode(): Value of the 'AddlCmdLine' control is: " + GetPropertyFromValuesXml(propertiesXml, "AddlCmdLine"));
                    node.Attributes[propertyValue].Value = GetPropertyFromValuesXml(propertiesXml, "AddlCmdLine");

                    if ((string.Compare(paramType, "StdOut", StringComparison.OrdinalIgnoreCase) == 0) ||
                        (string.Compare(paramType, "StdErr", StringComparison.OrdinalIgnoreCase) == 0))
                    {
                        //Logline("ReplaceCmdLineVarsInNode(): Leaving parameter type as StdOut or StdErr");
                    }
                    else
                    {
                        //Logline("ReplaceCmdLineVarsInNode(): Changing parameter type to String");
                        node.Attributes[propertyName].Value = "String";
                    }
                    //Logline("ReplaceCmdLineVarsInNode(): Successfully put the propertyValues in the task Node. ");
                    return node;
                    //}
                    //else
                    //{
                    //    Logline("ReplaceCmdLineVarsInNode():  ### ERROR ### could not find a propertyValue in properties XML for the CommandLine control propertyValue");
                    //    return null;
                    //}
                }
                else
                {
                    //Logline("ReplaceCmdLineVarsInNode(): Checkbox for addl command line was not checked, so not using this parameter");
                    node.ParentNode.RemoveChild(node);
                    return null;
                }
            }
            else
            {
                //Logline("ReplaceCmdLineVarsInNode(): Value of the parameter type is not 'cmdline' or 'addlcmdline'");
                return node;
            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private XmlDocument CreateTaskStepXml()
        {
                //Logline("CreateTaskStepXml:   starting...");
                XmlDocument taskFile = new XmlDocument();
                XmlElement topNode = taskFile.CreateElement("ClientTaskFile");
                XmlAttribute attrib = taskFile.CreateAttribute("SchemaVersion");
                attrib.Value = "1.0";
                topNode.SetAttributeNode(attrib);
                XmlAttribute attrib2 = taskFile.CreateAttribute("Created");
                attrib2.Value = IntegrationKitUtilities.GetXsdDateTime(DateTime.Now);
                topNode.SetAttributeNode(attrib2);
                taskFile.AppendChild(topNode);
                //Logline("CreateTaskStepXml:   created XML document. Returning...");
                return taskFile;
        }
               
        //public XmlNode AddTaskStepParameter(XmlNode taskStep, string switchName, string propertyValue, string typeName)
        //{
        //    try
        //    {
        //        XmlNode node = null;
        //        return node;
        //    }
        //    catch (Exception exceptionInfo)
        //    {
        //        LogException(exceptionInfo);
        //        return null;
        //    }
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <param taskName="propertyValues"></param>
        /// <param taskName="propertyName"></param>
        /// <returns></returns>
        private string GetPropertyFromValuesXml(XmlDocument valuesXml, string propertyName)
        {
                //Logline("GetPropertyFromValuesXml: Starting...");
                if (valuesXml != null)
                {
                    if (propertyName != null)
                    {
                        XmlNode propNode = IntegrationKitUtilities.GetXmlNode(valuesXml, "//Value[@name='" + propertyName + "']");
                        if (propNode != null)
                        {
                            //Logline("GetPropertyFromValuesXml: found a propertyValue node for this property. OuterXml is: \n\n" + propNode.OuterXml + "\n\n");
                            string content = propNode.InnerXml.ToString();
                            if (content != null)
                            {
                                content = content.Replace("<![CDATA[", "");
                                content = content.Replace("]]>", "");

                                //Logline("GetPropertyFromValuesXml:  Value for property: " + propertyName + " is " + content);
                                return content;
                            }
                            else
                            {
                                //Logline("GetPropertyFromValuesXml:  Value node found, but no propertyValue string found in XML for property: " + propertyName + "(valid xml propertiesXml, valid node, but no propertyValue)");
                                return null;
                            }
                        }
                        else
                        {
                            //Logline("GetPropertyFromValuesXml:  Value node not found in XML for property: " + propertyName);
                            return null;
                        }
                    }
                    else
                    {
                        //Logline("GetPropertyFromValuesXml: property taskName passed in was null");
                        return null;
                    }
                }
                else
                {
                    //Logline("GetPropertyFromValuesXml: XmlDocument passed in was null");
                    return null;
                }
            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param taskName="propertyValues"></param>
        /// <param taskName="propertyName"></param>
        /// <returns></returns>
        private Dictionary<string, string> GetListFromValuesXml(XmlDocument valuesXml, string propertyName)
        {
                //Logline("GetListFromValuesXml: Starting...");
                if (valuesXml != null)
                {
                    if (propertyName != null)
                    {
                        XmlNodeList propNodes = IntegrationKitUtilities.GetXmlNodeList(valuesXml, "//Value[@name='" + propertyName + "']");
                        if (propNodes != null)
                        {
                            //Logline("GetListFromValuesXml: found " + propNodes.Count + " propertyValue nodes for this property. ");
                            Dictionary<string, string> varList = new Dictionary<string, string>();
                            foreach (XmlNode propNode in propNodes)
                            {
                                string content = propNode.InnerXml.ToString();
                                if (content != null)
                                {
                                    content = content.Replace("<![CDATA[", "");
                                    content = content.Replace("]]>", "");

                                    //Logline("GetListFromValuesXml:  Value for property: " + propertyName + " is " + content);
                                    string[] newContent = content.Split(new char[] { '|' });
                                    try
                                    {
                                        //Logline("GetListFromValuesXml:  Saving to list as: " + newContent[0] + " = " + newContent[1]);
                                        varList.Add(newContent[0], newContent[1]);
                                    }
                                    catch (ArgumentException)
                                    {
                                        //Logline("GetListFromValuesXml:  That variable taskName already exists in the list. Skipping");
                                    }
                                }
                                else
                                {
                                    //Logline("GetListFromValuesXml:  Value node found, but no propertyValue string found in XML for property: " + propertyName + "(valid xml propertiesXml, valid node, but no propertyValue)");
                                }
                            }
                            return varList;
                        }
                        else
                        {
                            //Logline("GetListFromValuesXml:  Value node not found in XML for property: " + propertyName);
                            return null;
                        }
                    }
                    else
                    {
                        //Logline("GetListFromValuesXml: property taskName passed in was null");
                        return null;
                    }
                }
                else
                {
                   LogLine("GetListFromValuesXml: XmlDocument passed in was null");
                   return null;
                }
            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param taskName="valuesXml"></param>
        /// <param taskName="propertyName"></param>
        /// <param taskName="propertyValue"></param>
        /// <returns></returns>
        private XmlDocument PutValueInPropertiesXml(XmlDocument valuesXml, string propertyName, string propertyValue)
        {
                //Logline("PutValueInPropertiesXml: starting...");

                if (valuesXml != null)
                {
                    //Logline("PutValueInPropertiesXml: XmlDocument passed in was not null");
                    //propertiesXml = propertyValues;
                    if (propertyName != null)
                    {
                        //Logline("PutValueInPropertiesXml: property name passed in was " + propertyName);
                        XmlNode node = IntegrationKitUtilities.GetXmlNode(valuesXml, "//Value[@name='" + propertyName + "']");
                        if (node != null)
                        {
                            //Logline("PutValueInPropertiesXml: Found xml node in properties XML for property name = " + propertyName + ". Adding a new propertyValue: " + propertyValue);
                            if (string.IsNullOrEmpty(propertyValue))
                            {
                                node.ParentNode.RemoveChild(node);
                            }
                            else
                            {
                                node.InnerXml = "<![CDATA[" + propertyValue + "]]>";
                            }
                            //valuesXml.Normalize();
                            //Logline("PutValueInPropertiesXml: XML contents now: \n\n" + valuesXml.OuterXml + "\n");
                            return valuesXml;
                        }
                        else
                        {
                            if (!string.IsNullOrEmpty(propertyValue))
                            {
                                //Logline("PutValueInPropertiesXml: Did not find property name = " + propertyName + ". Adding it to the properties XML");

                                XmlElement rootNode = valuesXml.DocumentElement;
                                XmlElement elem = valuesXml.CreateElement("Value");
                                elem.InnerXml = "<![CDATA[" + propertyValue + "]]>";
                                XmlAttribute attrib = valuesXml.CreateAttribute("name");
                                attrib.Value = propertyName;
                                elem.SetAttributeNode(attrib);
                                rootNode.AppendChild(elem);
                                //Logline("PutValueInPropertiesXml: Added '" + propertyName + "' to properties XML with a propertyValue of '" + propertyValue + "'");
                                //Logline("PutValueInPropertiesXml: XML contents now: \n\n" + valuesXml.OuterXml + "\n");
                                //valuesXml.Normalize();
                            }
                            else
                            {
                                //Logline("PutValueInPropertiesXml: Property propertyValue was null. Not adding a node.");
                            }
                        }
                    }
                    else
                    {
                        //Logline("PutValueInPropertiesXml: property taskName passed in was null");
                    }
                }
                else
                {
                    //Logline("PutValueInPropertiesXml: XmlDocument passed in was null");
                }
                return valuesXml;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param taskName="valuesXml"></param>
        /// <param taskName="propertyName"></param>
        /// <param taskName="propertyValues"></param>
        /// <returns></returns>
        private XmlDocument PutListInPropertiesXml(XmlDocument valuesXml, string propertyName, Dictionary<string, string> propertyValues)
        {
                //Logline("PutListInPropertiesXml: starting...");

                if (valuesXml != null)
                {
                    if (propertyName != null)
                    {
                        XmlNodeList nodes = IntegrationKitUtilities.GetXmlNodeList(valuesXml, "//Value[@name='" + propertyName + "']");
                        if (nodes != null)
                        {
                            LogLine("PutListInPropertiesXml: Found " + nodes.Count + " nodes in properties XML for property name = " + propertyName + ". Removing them and replacing them.");
                            //XmlNode topNode = GetXmlNode(valuesXml, "//Values");

                            int j = nodes.Count;
                            for (int i = 0; i < j; i++)
                            {
                                //Logline("PutListInPropertiesXml(): Removing node " + i);
                                nodes[i].ParentNode.RemoveChild(nodes[i]);
                            }

                            //nodes = GetXmlNodeList(valuesXml, "//Value[@name='" + propertyName + "']");

                            XmlElement rootNode = valuesXml.DocumentElement;

                            foreach (KeyValuePair<string, string> kvp in propertyValues)
                            {
                                //Logline("PutListInPropertiesXml(): Adding variable to the properties XML: " + kvp.Key + " = " + kvp.Value);

                                XmlElement elem = valuesXml.CreateElement("Value");

                                elem.InnerXml = "<![CDATA[" + kvp.Key + "|" + kvp.Value + "]]>";
                                XmlAttribute attrib = valuesXml.CreateAttribute("name");
                                attrib.Value = propertyName;
                                elem.SetAttributeNode(attrib);
                                rootNode.AppendChild(elem);
                                //Logline("PutListInPropertiesXml: Added '" + propertyName + "' to properties XML with a propertyValue of '" + kvp.Key + "|" + kvp.Value + "'");
                            }
                           LogLine("\n\nXML contents now: \n\n" + valuesXml.OuterXml + "\n\n");
                            valuesXml.Normalize();
                            return valuesXml;
                        }
                        else
                        {
                            if (propertyValues != null)
                            {
                                //Logline("PutListInPropertiesXml: Adding propertyValues to the properties XML");
                                XmlElement rootNode = valuesXml.DocumentElement;

                                foreach (KeyValuePair<string, string> kvp in propertyValues)
                                {
                                    //Logline("PutListInPropertiesXml(): Adding variable to the properties XML: " + kvp.Key + " = " + kvp.Value);
                                    XmlElement elem = valuesXml.CreateElement("Value");
                                    elem.InnerXml = "<![CDATA[" + kvp.Key + "|" + kvp.Value + "]]>";
                                    XmlAttribute attrib = valuesXml.CreateAttribute("name");
                                    attrib.Value = propertyName;
                                    elem.SetAttributeNode(attrib);
                                    rootNode.AppendChild(elem);
                                    //Logline("PutListInPropertiesXml: Added '" + propertyName + "' to properties XML with a propertyValue of '" + kvp.Key + "|" + kvp.Value + "'");
                                }
                               LogLine("\n\nXML contents now: \n\n" + valuesXml.OuterXml + "\n\n");
                                //valuesXml.Normalize();
                            }
                            else
                            {
                                //Logline("PutListInPropertiesXml: Property propertyValues list was null. Not adding a node.");
                            }
                        }
                    }
                    else
                    {
                        //Logline("PutListInPropertiesXml: property taskName passed in was null");
                    }
                }
                else
                {
                   LogLine("PutListInPropertiesXml: XmlDocument passed in was null");
                }
                return valuesXml;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param taskName="dataGrid"></param>
        /// <returns></returns>
        private Dictionary<string, string> GetAdditionalVariablesList(DataGridView dataGrid)
        {
            if (dataGrid.Rows.Count > 0)
            {
                Dictionary<string, string> varList = new Dictionary<string, string>();

                for (int i = 0; i < dataGrid.Rows.Count - 1; i++)
                {
                    //modified 5/13/09 by rhearn to fix issue 4392 (var type not being saved)
                    // 
                    //  1. fixed type in "variableType" line below which was referring to Cells[3] instead of Cells[2]
                    //  2. modified key value to be "[varType]varName" instead of just varName so that the three values could be stored
                    string variableName = dataGrid.Rows[i].Cells[0].Value.ToString().Trim();
                    string variableValue = dataGrid.Rows[i].Cells[1].Value.ToString().Trim();
                    string variableType = dataGrid.Rows[i].Cells[2].Value.ToString().Trim();
                    try
                    {
                        LogLine("GetAdditionalVariablesList: Saving user-defined variable: [" + variableType + "]" + variableName + " = " + variableValue);
                        varList.Add("[" + variableType + "]" + variableName, variableValue);
                    }
                    catch (ArgumentException)
                    {
                        LogLine("GetAdditionalVariablesList: A propertyValue already exists in the variable list for " + "[" + variableType + "]" + variableName);
                    }
                    catch (Exception)
                    {
                        //Logline("GetAdditionalVariablesList: General exception when adding a variable to the var list");
                        return null;
                    }
                }
                return varList;
            }
            else
            {
                //Logline("GetAdditionalVariablesList: There are no additional variables to save");
                return null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private XmlDocument LoadXmlDocument(string baseRegistryKey)
        {
            try
            {

                LogLine("LoadXmlDocument: Starting...");
                // 
                // Loads an XML file, which is by default stored in a directory on the site
                // server under the Deployment Pack install path. The path is saved in
                // a registry key during installation.
                //
                string XMLFile = IntegrationKitUtilities.GetSafeRegistryStringValue("HKEY_LOCAL_MACHINE", BaseRegistryKey64, Properties.Resources.Registry_XMLConfigurationFile);

                installDir = IntegrationKitUtilities.GetSafeRegistryStringValue("HKEY_LOCAL_MACHINE", BaseRegistryKey64, Properties.Resources.Registry_InstallationDirectory);

                if (string.IsNullOrEmpty(installDir))
                {
                    richTextBoxMainFormErrorDisplay.Text = string.Format(Properties.Resources.LoadXmlDocument_InstallDirKeyNotFound, BaseRegistryKey64 + "\\" + Properties.Resources.Registry_InstallationDirectory);
                    LogLine(string.Format("LoadXmlDocument: " + Properties.Resources.LoadXmlDocument_InstallDirKeyNotFound, BaseRegistryKey64 + "\\" + Properties.Resources.Registry_InstallationDirectory));
                    return null;
                }

                if (string.IsNullOrEmpty(XMLFile))
                {
                    richTextBoxMainFormErrorDisplay.Text = string.Format(Properties.Resources.LoadXmlDocument_ConfigXmlKeyNotFound, BaseRegistryKey64 + "\\" + Properties.Resources.Registry_XMLConfigurationFile);
                    LogLine(string.Format("LoadXmlDocument: " + Properties.Resources.LoadXmlDocument_ConfigXmlKeyNotFound, BaseRegistryKey64 + "\\" + Properties.Resources.Registry_XMLConfigurationFile));
                    return null;
                }

                if (Directory.Exists(installDir) == false)
                {
                    richTextBoxMainFormErrorDisplay.Text = string.Format(Properties.Resources.LoadXmlDocument_InstallDirNotFound, BaseRegistryKey64 + "\\" + Properties.Resources.Registry_InstallationDirectory, installDir);
                    LogLine(string.Format("LoadXmlDocument: " + Properties.Resources.LoadXmlDocument_InstallDirNotFound, BaseRegistryKey64 + "\\" + Properties.Resources.Registry_InstallationDirectory, installDir));
                    return null;
                }

                if (File.Exists(XMLFile) == false)
                {
                    // the registry key had a value but we could not find the file. Perhaps the key only specifies a filename?
                    if (XMLFile.Contains(@"\") == false)
                    {
                        // looks like this is just a filename. Try adding the path.
                        if (installDir.EndsWith(@"\") == false)
                        {
                            installDir += @"\";
                        }
                        XMLFile = installDir + XMLFile;

                    }
                    if (File.Exists(XMLFile) == false)
                    {
                        richTextBoxMainFormErrorDisplay.Text = string.Format(Properties.Resources.LoadXmlDocument_ConfigXmlNotFound, BaseRegistryKey64 + "\\" +
                            Properties.Resources.Registry_XMLConfigurationFile, BaseRegistryKey64 + "\\" +
                            Properties.Resources.Registry_InstallationDirectory, installDir);
                        LogLine(string.Format("LoadXmlDocument: " + Properties.Resources.LoadXmlDocument_ConfigXmlNotFound, BaseRegistryKey64 + "\\" +
                            Properties.Resources.Registry_XMLConfigurationFile, BaseRegistryKey64 + "\\" +
                            Properties.Resources.Registry_InstallationDirectory, installDir));
                        return null;
                    }

                }

                LogLine("LoadXmlDocument: Found XML file named in registry: " + XMLFile);
                XmlDocument Xmldoc = new XmlDocument();
                LogLine("LoadXmlDocument: Trying to load XML");

                try
                {
                    Xmldoc.Load(XMLFile);
                }
                catch (XmlException ex)
                {
                    richTextBoxMainFormErrorDisplay.Text = string.Format(Properties.Resources.ErrorDialog_XmlException, ex.TargetSite, ex.LineNumber, ex.LinePosition, ex.SourceUri, ex.Data, ex.InnerException);
                    LogLine(string.Format(Properties.Resources.ErrorLog_XmlException, ex.TargetSite, ex.LineNumber, ex.LinePosition, ex.SourceUri, ex.Data, ex.InnerException, ex.GetType().Name, ex.GetType().FullName, ex.GetType().Attributes, ex.GetType().DeclaringMethod));
                    return null;
                }

                // if program execution has not jumped to the catch statement here, the XML file was successfully loaded, 
                // so return the XML document object.
                LogLine("LoadXmlDocument: Loaded XML");
                return Xmldoc;
            }
            catch (Exception e)
            {
                LogLine("LoadXmlDocument: Exception occurred: " + e.Message + "\n" + e.StackTrace);
                return null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private bool ConfigurationAndActionSelectedAreSavedValues()
        {
            if ((string.Compare(IntegrationKitUtilities.GetComboBoxControlValue(comboBoxConfigType), GetPropertyFromValuesXml(PropertiesXml, "ConfigType"), StringComparison.OrdinalIgnoreCase) == 0) &&
                                (string.Compare(IntegrationKitUtilities.GetComboBoxControlValue(comboBoxAction), GetPropertyFromValuesXml(PropertiesXml, "ActionType"), StringComparison.OrdinalIgnoreCase) == 0))
            {
                return true;
            }
            else
            {
                return false;
            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private bool IsGetAction()
        {
            if (string.Compare(IntegrationKitUtilities.GetComboBoxControlValue(comboBoxAction), Properties.Resources.TSA_ActionType_Get,
                StringComparison.CurrentCultureIgnoreCase) == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private bool IsSetAction()
        {
            if (string.Compare(IntegrationKitUtilities.GetComboBoxControlValue(comboBoxAction), Properties.Resources.TSA_ActionType_Set,
                StringComparison.CurrentCultureIgnoreCase) == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Examines the configuration XML file to see if the control is disabled for this form for this action type
        /// </summary>
        /// <param name="formControl">The Control object for which to determine status</param>
        /// <param name="currentAction">Contains the "Get" or "Set" action node needed to find the value of the control settings</param>
        /// <returns></returns>
        private bool IsControlDisabled(Control formControl, XmlNode currentAction)
        {
            IntegrationKitUtilities.ArgumentNotNull(formControl, "formControl");
            IntegrationKitUtilities.ArgumentNotNull(currentAction, "currentAction");

            //the currentAction Xml contains the "Get" or "Set" action needed to find the following:
            //<Controls>
            //  <Control ControlType="Button" Name="buttonLaunchViewer" IsEnabled="false" IsVisible="false" />
            //</Controls>
            
            string controlName = formControl.Name;
            IntegrationKitUtilities.ArgumentNotNullOrEmpty(controlName, "controlName");
            XmlNode controlNode = IntegrationKitUtilities.GetXmlNode(currentAction, ".//Controls/Control[@Name='" + controlName + "']");
            if (controlNode != null)
            {
                bool isEnabled = true;
                string value = IntegrationKitUtilities.GetXmlAttribute(controlNode, "IsEnabled");
                if (bool.TryParse(value, out isEnabled))
                {
                    //successfully parsed - value is in isDisabled
                    if (isEnabled)
                    {
                        //the control was marked enabled, so it is "not disabled"
                        return false;
                    }
                    else
                    {
                        //the control was marked "not enabled", so it is "disabled"
                        return true;
                    }
                }
                //the value could not be parsed. By default the control is marked "not disabled" (below)
            }

            //the control was not found, so by default it is "not disabled"
            return false;
        }

        #region Logging / Debug

        /// <summary>
        /// 
        /// </summary>
        public void InitializeTraceLog(string registryKey, string fileName)
        {
            string logFilePath = string.Empty;
            try
            {
                if (string.IsNullOrEmpty(registryKey))
                {
                    return;
                }
                if (string.IsNullOrEmpty(fileName))
                {
                    return;
                }
                int logging = 0;
                               
                logging = IntegrationKitUtilities.GetSafeRegistryDwordValue("HKEY_LOCAL_MACHINE", registryKey, Properties.Resources.Registry_DebugLogging);
                
                if (logging != 0)
                {
                    if (LogFile == null)
                    {
                        string logDir = string.Empty;
                        logDir = IntegrationKitUtilities.GetSafeRegistryStringValue("HKEY_LOCAL_MACHINE", registryKey, Properties.Resources.Registry_InstallationDirectory);

                        if (string.IsNullOrEmpty(logDir))
                        {
                            MessageBox.Show("InitializeTraceLog: Unable to access the registry key:\n HKEY_LOCAL_MACHINE\\" + registryKey + "\\" + 
                                           Properties.Resources.Registry_InstallationDirectory + "\n\nPlease check your installation.");
                        }
                        if (Directory.Exists(logDir))
                        {
                            logFilePath = logDir + Path.DirectorySeparatorChar + fileName;
                        }
                        else
                        {
                            logFilePath = fileName;
                        }
                        FileStream fs = new FileStream(logFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite,8, true);

                        LogFile = new StreamWriter(fs);
                        DebugEnabled = true;
                        //return logFile;
                    }
                    else
                    {
                        DebugEnabled = true;
                    }
                }
                else
                {
                    DebugEnabled = false;
                    LogFile =  null;
                }

            }
            catch (IOException)
            {
                DialogHelper.ShowMessageBox("Unable to open log file : " + logFilePath);
                //throw;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="exceptioninfo"></param>
        public void LogException(Exception exceptioninfo)
        {
            IntegrationKitUtilities.LogException(LogFile, exceptioninfo, DebugEnabled);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="output"></param>
        public void LogLine(string output)
        {
            IntegrationKitUtilities.LogLine(LogFile, output, DebugEnabled);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="output"></param>
        /// <param name="obj"></param>
        public void LogLine(string output, IResultObject obj)
        {
            IntegrationKitUtilities.LogLine(LogFile, output, obj, DebugEnabled);
        }

        #endregion

    }
}
